/*************************************************************************
	> File Name: 1.server.c
	> Author: 
	> Mail: 
	> Created Time: 2021年01月28日 星期四 20时41分14秒
 ************************************************************************/

#include "head.h"
#define MAX_EVENTS 10

int main(int argc, char **argv) {
    int server_listen, sockfd, port, epollfd, nfds, conn_sock;
    struct epoll_event ev, events[MAX_EVENTS];
    if (argc != 2) {
        fprintf(stderr, "Usage : %s port!\n", argv[0]);
        exit(1);
    }
    port = atoi(argv[1]);
    if ((server_listen = socket_create(port)) < 0) {
        perror("socket_create");
        exit(1);
    }

    epollfd = epoll_create1(0);
    if (epollfd == -1) {
        perror("epoll_create1");
        exit(EXIT_FAILURE);
    }

    ev.events = EPOLLIN;
    ev.data.fd = server_listen;
    if (epoll_ctl(epollfd, EPOLL_CTL_ADD, server_listen, &ev) == -1) {
        perror("epoll_ctl: server_listen");
        exit(EXIT_FAILURE);
    }

    for(;;) {
        nfds = epoll_wait(epollfd, events, MAX_EVENTS, -1);
        if (nfds == -1) {
            perror("epoll_wait");
            exit(EXIT_FAILURE);
        }
        
        for (int i = 0; i < nfds, i++) {
            if (events[i].data.fd == server_listen) {
                struct sockaddr_in *client = (struct sockaddr_in *)malloc(sizeof(struct sockaddr_in));
                socklen_t len = sizeof(struct sockaddr_in);
                conn_sock = accept(server_listen, (struct sockaddr *)client, &len);
                if (conn_sock == -1) {
                    perror("accept");
                    exit(EXIT_FAILURE);
                }
                printf("%s is online\n", inet_ntoa(client.sin_addr));
                setnonblocking(conn_sock);
                ev.events = EPOLLIN | EPOLLET;
                ev.data.fd = conn_sock;
                ev.data.ptr = client;
                if (epoll_ctl(epollfd, EPOLL_CTL_ADD, conn_sock, &ev) == -1) {
                    perror("epoll_ctl: conn_sock");
                    exit(EXIT_FAILURE);
                }
            } else {
                char buff[512] = {0};
                char tobuff[1024] = {0};
                struct sockaddr_in *client = events[i].data.ptr;
                size_t ret = recv(events[i].data.fd, buff, sizeof(buff), 0);
                // 等于0说明没有东西， 小于0说明出错了
                if (ret <= 0) {
                    printf("<%s> is offline\n", inet_ntoa(client->sin_addr));
                    close(events[i].data.fd);
                    exit(1);
                }
                printf("<%s> : %s\n", inet_ntoa(client->sin_addr), buff);
                sprintf(tobuff, "I have recved your message : %s", buff);
                send(conn_sock, tobuff, strlen(tobuff), 0);
            }
        }
    }

    return 0;
}

